home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xfig.idb / usr / freeware / src / xfig / transfig.3.1.2 / fig2dev / read.c.z / read.c
Encoding:
C/C++ Source or Header  |  1997-09-09  |  27.8 KB  |  1,114 lines

  1. /*
  2.  * TransFig: Facility for Translating Fig code
  3.  * Copyright (c) 1985 Supoj Sutantavibul
  4.  * Copyright (c) 1991 Micah Beck
  5.  *
  6.  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  7.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  8.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  9.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  10.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  11.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  12.  * PERFORMANCE OF THIS SOFTWARE.
  13.  *
  14.  * The X Consortium, and any party obtaining a copy of these files from
  15.  * the X Consortium, directly or indirectly, is granted, free of charge, a
  16.  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
  17.  * nonexclusive right and license to deal in this software and
  18.  * documentation files (the "Software"), including without limitation the
  19.  * rights to use, copy, modify, merge, publish, distribute, sublicense,
  20.  * and/or sell copies of the Software, and to permit persons who receive
  21.  * copies from any such party to do so, with the only requirement being
  22.  * that this copyright notice remain intact.  This license includes without
  23.  * limitation a license to do the foregoing actions under any patents of
  24.  * the party supplying this software to the X Consortium.
  25.  */
  26.  
  27. /* 
  28.  *    FIG : Facility for Interactive Generation of figures
  29.  *
  30.  *    Copyright (c) 1985, 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  31.  *    January 1985.
  32.  *    1st revision : August 1985.
  33.  *    2nd revision : March 1988.
  34.  *
  35.  *    %W%    %G%
  36. */
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #include <errno.h>
  40. #include "alloc.h"
  41. #include "fig2dev.h"
  42. #include "object.h"
  43. #include "../patchlevel.h"
  44.  
  45. #if defined(hpux) || defined(SYSV) || defined(SVR4)
  46. #define bzero(s,n) memset((s),'\0',(n))
  47. #endif
  48.  
  49. extern int            errno;
  50.  
  51. extern F_arrow        *make_arrow();
  52. extern char        *calloc();
  53. extern double         floor(), ceil();
  54.  
  55. static void         read_colordef();
  56. static F_ellipse    *read_ellipseobject();
  57. static F_line        *read_lineobject();
  58. static F_text        *read_textobject();
  59. static F_spline        *read_splineobject();
  60. static F_arc        *read_arcobject();
  61. static F_compound    *read_compoundobject();
  62.  
  63. #define            FILL_CONVERT(f) \
  64.                 ((v2_flag || (f) < WHITE_FILL) \
  65.                     ? (v30_flag? f: (f-1)) : 20 - ((f)-1)*5)
  66.  
  67. #define            BUF_SIZE        1024
  68.  
  69. User_color        user_colors[MAX_USR_COLS];
  70. int            user_col_indx[MAX_USR_COLS];
  71. int            num_usr_cols;
  72. char            buf[BUF_SIZE];
  73. int            line_no = 0;
  74. int            num_object;
  75. int            v2_flag;    /* Protocol V2.0 or higher */
  76. int            v21_flag;    /* Protocol V2.1 or higher */
  77. int            v30_flag;    /* Protocol V3.0 or higher */
  78. float            THICK_SCALE;    /* convert line thickness from screen res. */
  79.  
  80. read_fail_message(file, err)
  81. char    *file;
  82. int    err;
  83. {
  84.     extern char    *sys_errlist[];
  85.  
  86.     if (err == 0)        /* Successful read */
  87.         return;
  88. #if !defined(hpux) && !defined(SYSV) && !defined(SVR4)
  89.     else if (err == ENAMETOOLONG)
  90.         put_msg("File name \"%s\" is too long", file);
  91. #endif
  92.     else if (err == ENOENT)
  93.         put_msg("File \"%s\" does not exist", file);
  94.     else if (err == ENOTDIR)
  95.         put_msg("A name in the path \"%s\" is not a directory", file);
  96.     else if (err == EACCES)
  97.         put_msg("Read access to file \"%s\" is blocked", file);
  98.     else if (err == EISDIR)
  99.         put_msg("File \"%s\" is a directory", file);
  100.     else if (err == -2) {
  101.         put_msg("File \"%s\" is empty", file);
  102.         }
  103.     else if (err == -1) {
  104.         /* Format error; relevant error message is already delivered */
  105.         }
  106.     else
  107.         put_msg("File \"%s\" is not accessable; %s", file, sys_errlist[err]);
  108.     }
  109.  
  110. /**********************************************************
  111. Read_fig returns :
  112.  
  113.      0 : successful read.
  114.     -1 : File is in incorrect format
  115.     -2 : File is empty
  116. err_no : if file can not be read for various reasons
  117.  
  118. The resolution (ppi) and the cooridnate system (coord_sys) are
  119. stored in obj->nwcorner.x and obj->nwcorner.x respectively.
  120. **********************************************************/
  121.  
  122. read_fig(file_name, obj)
  123. char        *file_name;
  124. F_compound    *obj;
  125. {
  126.     FILE        *fp;
  127.  
  128.     init_pats_used();
  129.     if ((fp = fopen(file_name, "r")) == NULL)
  130.         return(errno);
  131.     else
  132.         return(readfp_fig(fp, obj));
  133.     }
  134.  
  135. readfp_fig(fp, obj)
  136. FILE    *fp;
  137. F_compound    *obj;
  138. {
  139.     char        c;
  140.     int        status;
  141.  
  142.     num_object = 0;
  143.     num_usr_cols = 0;
  144.     c = fgetc(fp);
  145.     if (feof(fp)) return(-2);
  146.     ungetc(c, fp);
  147.     bzero((char*)obj, COMOBJ_SIZE);
  148.     if (c == '#')
  149.         status = read_objects(fp, obj);
  150.     else
  151.         status = read_1_3_objects(fp, obj);
  152.     (void)fclose(fp);
  153.     return(status);
  154.     }
  155.     
  156. int
  157. read_objects(fp, obj)
  158. FILE        *fp;
  159. F_compound    *obj;
  160. {
  161.     F_ellipse    *e, *le = NULL;
  162.     F_line        *l, *ll = NULL;
  163.     F_text        *t, *lt = NULL;
  164.     F_spline    *s, *ls = NULL;
  165.     F_arc        *a, *la = NULL;
  166.     F_compound    *c, *lc = NULL;
  167.     int        object, ppi, coord_sys;
  168.  
  169.     bzero((char*)obj, COMOBJ_SIZE);
  170.     (void)fgets(buf, BUF_SIZE, fp);    /* get the version line */
  171.     if (strlen(buf) > 0)
  172.         buf[strlen(buf)-1] = '\0';    /* remove newline */
  173.  
  174.     /* v2_flag is for version 2 or higher */
  175.     v2_flag = (!strncmp(buf, "#FIG 2", 6) || !strncmp(buf, "#FIG 3", 6));
  176.     /* v21_flag is for version 2.1 or higher */
  177.     v21_flag = (!strncmp(buf, "#FIG 2.1", 8) || !strncmp(buf, "#FIG 3", 6));
  178.     /* version 2.2 was only beta - 3.0 is the official release (they are identical) */
  179.     v30_flag = (!strncmp(buf, "#FIG 3", 6) || !strncmp(buf, "#FIG 2.2", 8));
  180.     if (strncmp(&buf[5],VERSION,3) > 0) {
  181.         put_msg("Fig file format (%s) newer than this version of fig2dev (%s), exiting",
  182.             &buf[5],VERSION);
  183.         exit(1);
  184.     }
  185.  
  186.     if (v30_flag) {
  187.         /* read the orientation spec (landscape/portrait) */
  188.         line_no++;
  189.         if (get_line(fp) < 0) {
  190.         put_msg("File is truncated at landscape/portrait specification.");
  191.         return(-1);
  192.         }
  193.         /* but set only of the user didn't specify the orientation
  194.            on the command line */
  195.         if (!orientspec)
  196.         landscape = !strncasecmp(buf,"land",4);
  197.  
  198.         /* now read the metric/inches spec OR centering spec */
  199.         line_no++;
  200.         if (get_line(fp) < 0) {
  201.         put_msg("File is truncated at metric/inches or centering specification.");
  202.         return(-1);
  203.         }
  204.         if ((strncasecmp(buf,"center",6) == 0) || 
  205.         (strncasecmp(buf,"flush",5) == 0)) {
  206.         center = strncasecmp(buf,"flush",5);
  207.         /* now read metric/inches spec */
  208.         line_no++;
  209.         if (get_line(fp) < 0) {
  210.             put_msg("File is truncated at metric/inches specification.");
  211.             return(-1);
  212.         }
  213.         }
  214.         /* if metric, scale magnification to correct for xfig display error */
  215.         if (strncasecmp(buf,"metric",5)==0)
  216.         mag *= 80.0/76.2;
  217.     }
  218.  
  219.     line_no++;
  220.     /* now read for resolution and coord_sys */
  221.     if (get_line(fp) < 0) {
  222.         put_msg("File is truncated at resolution specification.");
  223.         return(-1);
  224.         }
  225.     if (sscanf(buf,"%d%d\n", &ppi, &coord_sys) != 2) {
  226.         put_msg("Incomplete resolution information at line %d", line_no);
  227.         return(-1);
  228.         }
  229.  
  230.     THICK_SCALE = ppi/80;    /* convert line thickness from screen resolution */
  231.     obj->nwcorner.x = ppi;
  232.     obj->nwcorner.y = coord_sys;
  233.     while (get_line(fp) > 0) {
  234.         if (sscanf(buf, "%d", &object) != 1) {
  235.         put_msg("Incorrect format at line %d", line_no);
  236.         return(-1);
  237.         }
  238.         switch (object) {
  239.         case O_COLOR_DEF:
  240.             read_colordef(fp);
  241.             if (num_object) {
  242.             put_msg("Color definitions must come before other objects (line %d).",
  243.                 line_no);
  244.             return (-1);
  245.             }
  246.             num_usr_cols++;
  247.             break;
  248.         case O_POLYLINE :
  249.             if ((l = read_lineobject(fp)) == NULL) 
  250.             return(-1);
  251.             if (ll)
  252.             ll = (ll->next = l);
  253.             else 
  254.             ll = obj->lines = l;
  255.             num_object++;
  256.             break;
  257.         case O_SPLINE :
  258.             if ((s = read_splineobject(fp)) == NULL) 
  259.             return(-1);
  260.             if (ls)
  261.             ls = (ls->next = s);
  262.             else 
  263.             ls = obj->splines = s;
  264.             num_object++;
  265.             break;
  266.         case O_ELLIPSE :
  267.             if ((e = read_ellipseobject()) == NULL) 
  268.             return(-1);
  269.             if (le)
  270.             le = (le->next = e);
  271.             else 
  272.             le = obj->ellipses = e;
  273.             num_object++;
  274.             break;
  275.         case O_ARC :
  276.             if ((a = read_arcobject(fp)) == NULL) 
  277.             return(-1);
  278.             if (la)
  279.             la = (la->next = a);
  280.             else 
  281.             la = obj->arcs = a;
  282.             num_object++;
  283.             break;
  284.         case O_TEXT :
  285.             if ((t = read_textobject(fp)) == NULL) 
  286.             return(-1);
  287.             if (lt)
  288.             lt = (lt->next = t);
  289.             else 
  290.             lt = obj->texts = t;
  291.             num_object++;
  292.             break;
  293.         case O_COMPOUND :
  294.             if ((c = read_compoundobject(fp)) == NULL) 
  295.             return(-1);
  296.             if (lc)
  297.             lc = (lc->next = c);
  298.             else 
  299.             lc = obj->compounds = c;
  300.             num_object++;
  301.             break;
  302.         default :
  303.             put_msg("Incorrect object code at line %d", line_no);
  304.             return(-1);
  305.         } /*  switch */
  306.         } /*  while */
  307.     if (feof(fp))
  308.         return(0);
  309.     else
  310.         return(errno);
  311.     } /*  read_objects */
  312.  
  313. static void
  314. read_colordef(fp)
  315.     FILE       *fp;
  316.     int            c,r,g,b;
  317.  
  318.     if ((sscanf(buf, "%*d %d #%02x%02x%02x", &c, &r, &g, &b) != 4) ||
  319.         (c < NUM_STD_COLS)) {
  320.     buf[strlen(buf)-1]='\0';    /* remove the newline */
  321.     put_msg("Invalid color definition: %s, setting to black (#00000).",buf);
  322.     r=g=b=0;
  323.     }
  324.     user_col_indx[num_usr_cols] = c;
  325.     user_colors[num_usr_cols].r = r;
  326.     user_colors[num_usr_cols].g = g;
  327.     user_colors[num_usr_cols].b = b;
  328. }
  329.  
  330. fix_color(color)
  331.     int            *color;
  332. {
  333.     int            i;
  334.     if (*color < NUM_STD_COLS)
  335.     return;
  336.     for (i=0; i<num_usr_cols; i++)
  337.     if (*color == user_col_indx[i]) {
  338.         *color = i+NUM_STD_COLS;
  339.         return;
  340.     }
  341.     put_msg("Cannot locate user color %d, using default color for line %d.",
  342.         *color,line_no);
  343.     *color = DEFAULT;
  344.     return;
  345. }
  346.  
  347. static F_arc *
  348. read_arcobject(fp)
  349. FILE    *fp;
  350. {
  351.     F_arc    *a;
  352.     int    n, fa, ba;
  353.     int    type, style;
  354.     double    thickness, wid, ht;
  355.  
  356.     if (NULL == (Arc_malloc(a))) {
  357.         put_msg(Err_mem);
  358.         return(NULL);
  359.         }
  360.     a->pen = 0;
  361.     a->fill_style = 0;
  362.     a->for_arrow = NULL;
  363.     a->back_arrow = NULL;
  364.     a->next = NULL;
  365.     if (v30_flag) {
  366.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%lf%lf%d%d%d%d%d%d\n",
  367.         &a->type, &a->style, &a->thickness, 
  368.         &a->pen_color, &a->fill_color, &a->depth, &a->pen, &a->fill_style, 
  369.         &a->style_val, &a->cap_style,
  370.         &a->direction, &fa, &ba,
  371.         &a->center.x, &a->center.y, 
  372.         &a->point[0].x, &a->point[0].y, 
  373.         &a->point[1].x, &a->point[1].y, 
  374.         &a->point[2].x, &a->point[2].y);
  375.     } else {
  376.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d\n",
  377.         &a->type, &a->style, &a->thickness, 
  378.         &a->pen_color, &a->depth, &a->pen, &a->fill_style, 
  379.         &a->style_val, &a->direction, &fa, &ba,
  380.         &a->center.x, &a->center.y, 
  381.         &a->point[0].x, &a->point[0].y, 
  382.         &a->point[1].x, &a->point[1].y, 
  383.         &a->point[2].x, &a->point[2].y);
  384.         a->fill_color = a->pen_color;
  385.         a->cap_style = 0;        /* butt line cap */
  386.     }
  387.     if ((v30_flag && n != 21) || (!v30_flag && n != 19)) {
  388.         put_msg(Err_incomp, "arc", line_no);
  389.         free((char*)a);
  390.         return(NULL);
  391.         }
  392.     a->thickness *= THICK_SCALE;
  393.     a->fill_style = FILL_CONVERT(a->fill_style);
  394.     /* keep track if pattern is used */
  395.     note_pattern(a->fill_style);
  396.     fix_color(&a->pen_color);
  397.     fix_color(&a->fill_color);
  398.     skip_comment(fp);
  399.     if (fa) {
  400.         line_no++;
  401.         if (fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht) != 5) {
  402.         fprintf(stderr, Err_incomp, "arc", line_no);
  403.         return(NULL);
  404.         }
  405.         skip_line(fp);
  406.         a->for_arrow = make_arrow(type, style, thickness, wid, ht);
  407.         skip_comment(fp);
  408.         }
  409.     skip_comment(fp);
  410.     if (ba) {
  411.         line_no++;
  412.         if (fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht) != 5) {
  413.         fprintf(stderr, Err_incomp, "arc", line_no);
  414.         return(NULL);
  415.         }
  416.         skip_line(fp);
  417.         a->back_arrow = make_arrow(type, style, thickness, wid, ht);
  418.         }
  419.     return(a);
  420.     }
  421.  
  422. static F_compound *
  423. read_compoundobject(fp)
  424. FILE    *fp;
  425. {
  426.     F_arc        *a, *la = NULL;
  427.     F_ellipse    *e, *le = NULL;
  428.     F_line        *l, *ll = NULL;
  429.     F_spline    *s, *ls = NULL;
  430.     F_text        *t, *lt = NULL;
  431.     F_compound    *com, *c, *lc = NULL;
  432.     int        n, object;
  433.  
  434.     Compound_malloc(com);
  435.     com->arcs = NULL;
  436.     com->ellipses = NULL;
  437.     com->lines = NULL;
  438.     com->splines = NULL;
  439.     com->texts = NULL;
  440.     com->compounds = NULL;
  441.     com->next = NULL;
  442.     n = sscanf(buf, "%*d%d%d%d%d\n", &com->nwcorner.x, &com->nwcorner.y,
  443.         &com->secorner.x, &com->secorner.y);
  444.     if (n != 4) {
  445.         put_msg(Err_incomp, "compound", line_no);
  446.         free((char*)com);
  447.         return(NULL);
  448.         }
  449.     while (get_line(fp) > 0) {
  450.         if (sscanf(buf, "%d", &object) != 1) {
  451.         put_msg(Err_incomp, "compound", line_no);
  452.         free_compound(&com);
  453.         return(NULL);
  454.         }
  455.         switch (object) {
  456.         case O_POLYLINE :
  457.             if ((l = read_lineobject(fp)) == NULL) { 
  458.             free_line(&l);
  459.             return(NULL);
  460.             }
  461.             if (ll)
  462.             ll = (ll->next = l);
  463.             else 
  464.             ll = com->lines = l;
  465.             break;
  466.         case O_SPLINE :
  467.             if ((s = read_splineobject(fp)) == NULL) { 
  468.             free_spline(&s);
  469.             return(NULL);
  470.             }
  471.             if (ls)
  472.             ls = (ls->next = s);
  473.             else 
  474.             ls = com->splines = s;
  475.             break;
  476.         case O_ELLIPSE :
  477.             if ((e = read_ellipseobject()) == NULL) { 
  478.             free_ellipse(&e);
  479.             return(NULL);
  480.             }
  481.             if (le)
  482.             le = (le->next = e);
  483.             else 
  484.             le = com->ellipses = e;
  485.             break;
  486.         case O_ARC :
  487.             if ((a = read_arcobject(fp)) == NULL) { 
  488.             free_arc(&a);
  489.             return(NULL);
  490.             }
  491.             if (la)
  492.             la = (la->next = a);
  493.             else 
  494.             la = com->arcs = a;
  495.             break;
  496.         case O_TEXT :
  497.             if ((t = read_textobject(fp)) == NULL) { 
  498.             free_text(&t);
  499.             return(NULL);
  500.             }
  501.             if (lt)
  502.             lt = (lt->next = t);
  503.             else 
  504.             lt = com->texts = t;
  505.             break;
  506.         case O_COMPOUND :
  507.             if ((c = read_compoundobject(fp)) == NULL) { 
  508.             free_compound(&c);
  509.             return(NULL);
  510.             }
  511.             if (lc)
  512.             lc = (lc->next = c);
  513.             else 
  514.             lc = com->compounds = c;
  515.             break;
  516.         case O_END_COMPOUND :
  517.             return(com);
  518.         default :
  519.             put_msg("Wrong object code at line %d", line_no);
  520.             return(NULL);
  521.         } /*  switch */
  522.         }
  523.     if (feof(fp))
  524.         return(com);
  525.     else
  526.         return(NULL);
  527.     }
  528.  
  529. static F_ellipse *
  530. read_ellipseobject()
  531. {
  532.     F_ellipse    *e;
  533.     int        n;
  534.  
  535.     Ellipse_malloc(e);
  536.     e->fill_style = 0;
  537.     e->pen = 0;
  538.     e->next = NULL;
  539.     if (v30_flag) {
  540.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d\n",
  541.         &e->type, &e->style, &e->thickness,
  542.         &e->pen_color, &e->fill_color, &e->depth, &e->pen, &e->fill_style,
  543.         &e->style_val, &e->direction, &e->angle,
  544.         &e->center.x, &e->center.y, 
  545.         &e->radiuses.x, &e->radiuses.y, 
  546.         &e->start.x, &e->start.y, 
  547.         &e->end.x, &e->end.y);
  548.     } else {
  549.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d\n",
  550.         &e->type, &e->style, &e->thickness,
  551.         &e->pen_color, &e->depth, &e->pen, &e->fill_style,
  552.         &e->style_val, &e->direction, &e->angle,
  553.         &e->center.x, &e->center.y, 
  554.         &e->radiuses.x, &e->radiuses.y, 
  555.         &e->start.x, &e->start.y, 
  556.         &e->end.x, &e->end.y);
  557.         e->fill_color = e->pen_color;
  558.     }
  559.     if ((v30_flag && n != 19) || (!v30_flag && n != 18)) {
  560.         put_msg(Err_incomp, "ellipse", line_no);
  561.         free((char*)e);
  562.         return(NULL);
  563.         }
  564.     fix_color(&e->pen_color);
  565.     fix_color(&e->fill_color);
  566.     e->thickness *= THICK_SCALE;
  567.     e->fill_style = FILL_CONVERT(e->fill_style);
  568.     /* keep track if pattern is used */
  569.     note_pattern(e->fill_style);
  570.     return(e);
  571.     }
  572.  
  573. static F_line *
  574. read_lineobject(fp)
  575. FILE    *fp;
  576. {
  577.     F_line    *l;
  578.     F_point    *p, *q;
  579.     int    n, x, y, fa, ba;
  580.     int    type, style, radius_flag;
  581.     double    thickness, wid, ht;
  582.     int    npts;
  583.  
  584.     Line_malloc(l);
  585.     l->points = NULL;
  586.     l->pen = 0;
  587.     l->fill_style = 0;
  588.     l->for_arrow = NULL;
  589.     l->back_arrow = NULL;
  590.     l->next = NULL;
  591.     l->join_style = 0;
  592.     l->cap_style = 0;        /* butt line cap */
  593.  
  594.     sscanf(buf,"%*d%d",&l->type);    /* get the line type */
  595.  
  596.     radius_flag = v30_flag || v21_flag || (v2_flag && l->type == T_ARC_BOX);
  597.     if (radius_flag) {
  598.         if (v30_flag) {
  599.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%d%d",
  600.         &l->type,&l->style,&l->thickness,&l->pen_color,&l->fill_color,
  601.         &l->depth,&l->pen,&l->fill_style,&l->style_val,
  602.         &l->join_style,&l->cap_style,
  603.         &l->radius,&fa,&ba,&npts);
  604.         } else {
  605.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d",
  606.         &l->type,&l->style,&l->thickness,&l->pen_color,
  607.         &l->depth,&l->pen,&l->fill_style,&l->style_val,&l->radius,&fa, &ba);
  608.         l->fill_color = l->pen_color;
  609.         }
  610.     }
  611.     /* old format uses pen for radius of arc-box corners */
  612.     else
  613.         {
  614.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d",
  615.             &l->type,&l->style,&l->thickness,&l->pen_color,
  616.             &l->depth,&l->pen,&l->fill_style,&l->style_val,&fa,&ba);
  617.         l->fill_color = l->pen_color;
  618.         if (l->type == T_ARC_BOX)
  619.         {
  620.         l->radius = (int) l->pen;
  621.         l->pen = 0;
  622.         }
  623.         else
  624.         l->radius = 0;
  625.         }
  626.     if ((!radius_flag && n!=10) ||
  627.          (radius_flag && ((!v30_flag && n!=11)||(v30_flag && n!=15)))) {
  628.         put_msg(Err_incomp, "line", line_no);
  629.         free((char*)l);
  630.         return(NULL);
  631.         }
  632.     l->radius *= THICK_SCALE;
  633.     l->thickness *= THICK_SCALE;
  634.     l->fill_style = FILL_CONVERT(l->fill_style);
  635.     /* keep track if pattern is used */
  636.     note_pattern(l->fill_style);
  637.     fix_color(&l->pen_color);
  638.     fix_color(&l->fill_color);
  639.     skip_comment(fp);
  640.     if (fa) {
  641.         line_no++;
  642.         if (fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht) != 5) {
  643.         fprintf(stderr, Err_incomp, "line", line_no);
  644.         return(NULL);
  645.         }
  646.         skip_line(fp);
  647.         l->for_arrow = make_arrow(type, style, thickness, wid, ht);
  648.         skip_comment(fp);
  649.         }
  650.     if (ba) {
  651.         line_no++;
  652.         if (fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht) != 5) {
  653.         fprintf(stderr, Err_incomp, "line", line_no);
  654.         return(NULL);
  655.         }
  656.         skip_line(fp);
  657.         l->back_arrow = make_arrow(type, style, thickness, wid, ht);
  658.         skip_comment(fp);
  659.         }
  660.         if (l->type == T_PIC_BOX) {
  661.         line_no++;
  662.         Pic_malloc(l->pic);
  663.         if (l->pic  == NULL) {
  664.             free((char *) l);
  665.             return (NULL);
  666.         }
  667.         if (fscanf(fp, "%d %s", &l->pic->flipped, l->pic->file) != 2) {
  668.                 put_msg(Err_incomp,
  669.                 "Picture object", line_no);
  670.                 fprintf(stderr, Err_incomp,
  671.                 "Picture object", line_no);
  672.             return (NULL);
  673.         }
  674.         } else
  675.         l->pic = NULL;
  676.  
  677.     if (NULL == (l->points = Point_malloc(p))) {
  678.         put_msg(Err_mem);
  679.         return(NULL);
  680.         }
  681.     p->next = NULL;
  682.     if (fscanf(fp, "%d%d", &p->x, &p->y) != 2) {
  683.         put_msg(Err_incomp, "line", line_no);
  684.         free_linestorage(l);
  685.         return(NULL);
  686.         }
  687.     if (!v30_flag)
  688.         npts = 1000000;
  689.     for (--npts; npts > 0; npts--) {
  690.         if (fscanf(fp, "%d%d", &x, &y) != 2) {
  691.         put_msg(Err_incomp, "line", line_no);
  692.         free_linestorage(l);
  693.         return(NULL);
  694.         }
  695.         if (!v30_flag && x == 9999) 
  696.         break;
  697.         if (NULL == (Point_malloc(q))) {
  698.         put_msg(Err_mem);
  699.         free_linestorage(l);
  700.         return(NULL);
  701.         }
  702.         q->x = x;
  703.         q->y = y;
  704.         q->next = NULL;
  705.         p->next = q;
  706.         p = q;
  707.         }
  708.     skip_line(fp);
  709.     return(l);
  710.     }
  711.  
  712. static F_spline *
  713. read_splineobject(fp)
  714. FILE    *fp;
  715. {
  716.     F_spline    *s;
  717.     F_point        *p, *q;
  718.     F_control    *cp, *cq;
  719.     int        c, n, x, y, fa, ba;
  720.     int        type, style, npts;
  721.     double        thickness, wid, ht;
  722.     double        lx, ly, rx, ry;
  723.  
  724.     Spline_malloc(s);
  725.     s->points = NULL;
  726.     s->controls = NULL;
  727.     s->pen = 0;
  728.     s->fill_style = 0;
  729.     s->for_arrow = NULL;
  730.     s->back_arrow = NULL;
  731.     s->next = NULL;
  732.  
  733.     if (v30_flag) {
  734.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d",
  735.             &s->type, &s->style, &s->thickness,
  736.         &s->pen_color, &s->fill_color,
  737.         &s->depth, &s->pen, &s->fill_style, &s->style_val,
  738.         &s->cap_style, &fa, &ba, &npts);
  739.     } else {
  740.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d",
  741.             &s->type, &s->style, &s->thickness, &s->pen_color,
  742.         &s->depth, &s->pen, &s->fill_style, &s->style_val, &fa, &ba);
  743.         s->fill_color = s->pen_color;
  744.         s->cap_style = 0;        /* butt line cap */
  745.     }
  746.     if ((v30_flag && n != 13) || (!v30_flag && n != 10)) {
  747.         put_msg(Err_incomp, "spline", line_no);
  748.         free((char*)s);
  749.         return(NULL);
  750.         }
  751.     s->thickness *= THICK_SCALE;
  752.     s->fill_style = FILL_CONVERT(s->fill_style);
  753.     /* keep track if pattern is used */
  754.     note_pattern(s->fill_style);
  755.     fix_color(&s->pen_color);
  756.     fix_color(&s->fill_color);
  757.     skip_comment(fp);
  758.     if (fa) {
  759.         line_no++;
  760.         if (fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht) != 5) {
  761.         fprintf(stderr, Err_incomp, "spline", line_no);
  762.         return(NULL);
  763.         }
  764.         skip_line(fp);
  765.         s->for_arrow = make_arrow(type, style, thickness, wid, ht);
  766.         skip_comment(fp);
  767.         }
  768.     if (ba) {
  769.         line_no++;
  770.         if (fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht) != 5) {
  771.         fprintf(stderr, Err_incomp, "spline", line_no);
  772.         return(NULL);
  773.         }
  774.         skip_line(fp);
  775.         s->back_arrow = make_arrow(type, style, thickness, wid, ht);
  776.         skip_comment(fp);
  777.         }
  778.  
  779.     /* Read points */
  780.     if ((n = fscanf(fp, "%d%d", &x, &y)) != 2) {
  781.         put_msg(Err_incomp, "spline", line_no);
  782.         free_splinestorage(s);
  783.         return(NULL);
  784.         };
  785.     if (NULL == (s->points = Point_malloc(p))) {
  786.         put_msg(Err_mem);
  787.         free_splinestorage(s);
  788.         return(NULL);
  789.         }
  790.     p->x = x; p->y = y;
  791.     c = 1;
  792.     if (!v30_flag)
  793.         npts = 1000000;
  794.     for (--npts; npts > 0; npts--) {
  795.         if (fscanf(fp, "%d%d", &x, &y) != 2) {
  796.         put_msg(Err_incomp, "spline", line_no);
  797.         p->next = NULL;
  798.         free_splinestorage(s);
  799.         return(NULL);
  800.         };
  801.         if (!v30_flag && x == 9999) 
  802.         break;
  803.         if (NULL == (Point_malloc(q))) {
  804.         put_msg(Err_mem);
  805.         free_splinestorage(s);
  806.         return(NULL);
  807.         }
  808.         q->x = x;
  809.         q->y = y;
  810.         p->next = q;
  811.         p = q;
  812.         c++;
  813.         }
  814.     p->next = NULL;
  815.     skip_line(fp);
  816.  
  817.     if (normal_spline(s)) return(s);
  818.  
  819.     skip_comment(fp);
  820.     /* Read controls */
  821.     if ((n = fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry)) != 4) {
  822.         put_msg(Err_incomp, "spline", line_no);
  823.         free_splinestorage(s);
  824.         return(NULL);
  825.         };
  826.     if (NULL == (s->controls = Control_malloc(cp))) {
  827.         put_msg(Err_mem);
  828.         free_splinestorage(s);
  829.         return(NULL);
  830.         }
  831.     cp->lx = lx; cp->ly = ly;
  832.     cp->rx = rx; cp->ry = ry;
  833.     while (--c) {
  834.         if (fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry) != 4) {
  835.         put_msg(Err_incomp, "spline", line_no);
  836.         cp->next = NULL;
  837.         free_splinestorage(s);
  838.         return(NULL);
  839.         };
  840.         if (NULL == (Control_malloc(cq))) {
  841.         put_msg(Err_mem);
  842.         cp->next = NULL;
  843.         free_splinestorage(s);
  844.         return(NULL);
  845.         }
  846.         cq->lx = lx; cq->ly = ly;
  847.         cq->rx = rx; cq->ry = ry;
  848.         cp->next = cq;
  849.         cp = cq;
  850.         }
  851.     cp->next = NULL;
  852.  
  853.     skip_line(fp);
  854.     return(s);
  855.     }
  856.  
  857. static F_text *
  858. read_textobject(fp)
  859. FILE    *fp;
  860. {
  861.     F_text    *t;
  862.     int    n, ignore = 0;
  863.     char    s[BUF_SIZE], s_temp[BUF_SIZE], junk[2];
  864.     int    more, len, l;
  865.  
  866.     Text_malloc(t);
  867.     t->font = 0;
  868.     t->size = 0.0;
  869.     t->next = NULL;
  870.  
  871. /* linux can't read 8-bit characters */
  872. #ifdef linux
  873.     {
  874.     char replaced;
  875.     int pos;
  876.     pos = 0;
  877.     len = strlen(buf);
  878.     while (((unsigned char) buf[pos] <= 'e' ) &&
  879.         ((unsigned char) buf[pos] >= ' ' ) && buf[pos] )
  880.             pos++;
  881.     replaced = buf[pos];
  882.     buf[pos]='f';
  883.     if (v30_flag) {    /* order of parms is more like other objects now */
  884.         n = sscanf(buf, "%*d%d%d%d%d%d%lf%lf%d%lf%lf%d%d%[^f]%[f]",
  885.         &t->type, &t->color, &t->depth, &t->pen,
  886.         &t->font, &t->size, &t->angle,
  887.         &t->flags, &t->height, &t->length,
  888.         &t->base_x, &t->base_y, s, junk);
  889.     } else {
  890.         n = sscanf(buf, "%*d%d%d%lf%d%d%d%lf%d%lf%lf%d%d%[^f]%[f]",
  891.         &t->type, &t->font, &t->size, &t->pen,
  892.         &t->color, &t->depth, &t->angle,
  893.         &t->flags, &t->height, &t->length,
  894.         &t->base_x, &t->base_y, s, junk);
  895.     }
  896.     n--;
  897.     if ( n < 13 ) {
  898.         put_msg(Err_incomp, "text", line_no);
  899.         free((char *) t);
  900.         return (NULL);
  901.        }
  902.     buf[pos]=replaced;
  903.     strcpy( s, buf+pos-strlen(s));
  904.     len=strlen(s);
  905.     if ( len && (s[len-1] ==  '\n') )
  906.         s[len-1]='\0';
  907.     len=strlen(s);
  908.     if (!v30_flag) {        /* if older version, remove the ^A */
  909.         if ( len && (s[len-1] ==  1) ) {
  910.         n++;
  911.         s[len-1]='\0';
  912.         }
  913.     }
  914.     }
  915.  
  916. #else
  917.     if (v30_flag) {    /* order of parms is more like other objects now,
  918.                string is now terminated with the literal '\001',
  919.                and 8-bit characters are represented as \xxx */
  920.  
  921.         n = sscanf(buf, "%*d%d%d%d%d%d%lf%lf%d%lf%lf%d%d%[^\n]",
  922.         &t->type, &t->color, &t->depth, &t->pen,
  923.         &t->font, &t->size, &t->angle,
  924.         &t->flags, &t->height, &t->length,
  925.         &t->base_x, &t->base_y, s, junk);
  926.     } else {
  927.         /* The text object is terminated by a CONTROL-A, so we read
  928.         everything up to the CONTROL-A and then read that character.
  929.         If we do not find the CONTROL-A on this line then this must
  930.         be a multi-line text object and we will have to read more. */
  931.  
  932.         n = sscanf(buf,"%*d%d%d%lf%d%d%d%lf%d%lf%lf%d%d%[^\1]%[\1]",
  933.         &t->type, &t->font, &t->size, &t->pen,
  934.         &t->color, &t->depth, &t->angle,
  935.         &t->flags, &t->height, &t->length, 
  936.         &t->base_x, &t->base_y, s, junk);
  937.     }
  938.     if ((n != 14) && (n != 13)) {
  939.       put_msg(Err_incomp, "text", line_no);
  940.       free((char*)t);
  941.        return(NULL);
  942.     }
  943. #endif
  944.     if (font_size) {
  945.         /* scale length/height of text by ratio of requested font size to actual size */
  946.         t->length = t->length * font_size/t->size;
  947.         t->height = t->height * font_size/t->size;
  948.         t->size = font_size;    /* and set to requested size */
  949.     }
  950.     if (t->size <= 0.0)
  951.         t->size = (float) DEFAULT_FONT_SIZE;
  952.     more = 0;
  953.     if (!v30_flag && n == 13)
  954.         more = 1;  /* in older xfig there is more if ^A wasn't found yet */
  955.     else if (v30_flag) {    /* in 3.0 there is more if \001 wasn't found */
  956.         len = strlen(s);
  957.         if ((strcmp(&s[len-4],"\\001") == 0) &&    /* if we find '\000' */
  958.             !(backslash_count(s, len-5) % 2)) {    /* and not '\\000' */
  959.             more = 0;                /* then there are no more lines */
  960.             s[len-4]='\0';            /* and get rid of the '\001' */
  961.         } else {
  962.         more = 1;
  963.         s[len++]='\n';            /* put back the end of line char */
  964.         s[len] = '\0';            /* and terminate it */
  965.         }
  966.     }
  967.     if (more) {
  968.     /* Read in the subsequent lines of the text if there is more than one. */
  969.       do {
  970.         fgets(buf, BUF_SIZE, fp);
  971.         line_no++;        /* As is done in get_line */
  972.         if (v30_flag) {
  973.         if (fgets(s_temp, BUF_SIZE, fp) == NULL)
  974.             break;
  975.         len = strlen(s_temp)-1;
  976.         if ((strncmp(&s_temp[len-4],"\\001",4) == 0) &&
  977.             !(backslash_count(s, len-5) % 2)) {
  978.             n=0;            /* found the '\001', set n to stop */
  979.             s_temp[len-4]='\0';    /* and get rid of the '\001' */
  980.         } else {
  981.             n=1;            /* keep going (more lines) */
  982.         }
  983.         } else {
  984.         if (fgets(buf, BUF_SIZE, fp) == NULL)
  985.             break;
  986.         n = sscanf(buf, "%[^\1]%[\1]", s_temp, junk);
  987.         }
  988.         /* Safety check */
  989.         if (strlen(s)+1 + strlen(s_temp)+1 > BUF_SIZE) {
  990.           /* Too many characters.  Ignore the rest. */
  991.           ignore = 1;
  992.         }
  993.         if (!ignore)
  994.           strcat(s, s_temp);
  995.       } while (n == 1);
  996.     }
  997.     if (v30_flag) {        /* now convert any \xxx to ascii characters */
  998.         if (strchr(s,'\\')) {
  999.         int num;
  1000.         len = strlen(s);
  1001.         for (l=0,n=0; l < len; l++) {
  1002.             if (s[l]=='\\') {
  1003.             if (l < len && s[l+1] != '\\') {
  1004.                 if (sscanf(&s[l+1],"%3o",&num)!=1) {
  1005.                 put_msg("Error in parsing text string on line",line_no);
  1006.                 return(NULL);
  1007.                 }
  1008.                 buf[n++]= (unsigned char) num;    /* put char in */
  1009.                 l += 3;            /* skip over digits */
  1010.             } else {
  1011.                 buf[n++] = s[++l];        /* "\\" */
  1012.             }
  1013.             } else {
  1014.             buf[n++] = s[l];        /* ordinary character */
  1015.             }
  1016.         }
  1017.         buf[n]='\0';        /* terminate */
  1018.         strcpy(s,buf);        /* copy back to s */
  1019.         }
  1020.     }
  1021.     if (strlen(s) == 0) 
  1022.         (void)strcpy(s, " ");
  1023.     t->cstring = (char*)calloc((unsigned)(strlen(s)), sizeof(char));
  1024.     if (NULL == t->cstring) {
  1025.         put_msg(Err_mem);
  1026.         free((char*)t);
  1027.         return(NULL);
  1028.     }
  1029.     (void)strcpy(t->cstring, s+1);
  1030.  
  1031.     if (!v21_flag && (t->font == 0 || t->font == DEFAULT))
  1032.         t->flags = ((t->flags != DEFAULT) ? t->flags : 0)
  1033.                 | SPECIAL_TEXT;
  1034.  
  1035.     if (v2_flag && !v21_flag && !special_text(t)) 
  1036.         t->flags = ((t->flags != DEFAULT) ? t->flags : 0)
  1037.                 | PSFONT_TEXT;
  1038.  
  1039.     /* keep the font number reasonable */
  1040.     if (t->font > MAXFONT(t))
  1041.         t->font = MAXFONT(t);
  1042.     fix_color(&t->color);
  1043.     return(t);
  1044. }
  1045.  
  1046. /* akm 28/2/95 - count consecutive backslashes backwards */
  1047. int
  1048. backslash_count(cp, start)
  1049. char cp[];
  1050. int start;
  1051. {
  1052.   int i, count = 0;
  1053.  
  1054.   for(i=start; i>=0; i--) {
  1055.     if (cp[i] == '\\')
  1056.     count++;
  1057.     else
  1058.     break;
  1059.   }
  1060.   return count;
  1061. }
  1062.  
  1063. get_line(fp)
  1064. FILE    *fp;
  1065. {
  1066.     while (1) {
  1067.         if (NULL == fgets(buf, BUF_SIZE, fp)) {
  1068.         return(-1);
  1069.         }
  1070.         line_no++;
  1071.         if (*buf != '\n' && *buf != '#') 
  1072.         return(1);    /* Skip empty and comment lines */
  1073.         }
  1074. }
  1075.  
  1076. skip_comment(fp)
  1077. FILE    *fp;
  1078. {
  1079.     char c;
  1080.  
  1081.     while ((c = fgetc(fp)) == '#') 
  1082.         skip_line(fp);
  1083.     if (c != '#') 
  1084.         ungetc(c, fp);
  1085. }
  1086.  
  1087. skip_line(fp)
  1088. FILE    *fp;
  1089. {
  1090.     while (fgetc(fp) != '\n') {
  1091.         if (feof(fp)) 
  1092.         return;
  1093.     }
  1094. }
  1095.  
  1096. /* keep track which patterns are used (if any) */
  1097. note_pattern(fill_style)
  1098. int     fill_style;
  1099. {
  1100.     if (fill_style >= NUMSHADES+NUMTINTS) {
  1101.         pattern_used[fill_style-NUMSHADES-NUMTINTS] = TRUE;
  1102.         pats_used = TRUE;
  1103.     }
  1104. }
  1105.     
  1106. init_pats_used()
  1107. {
  1108.     int i;
  1109.     pats_used = FALSE;
  1110.     for (i=0; i<NUMPATTERNS; i++)
  1111.         pattern_used[i] = FALSE;
  1112. }
  1113.